package utils

import (
	"fmt"
	"ginjwt/config"
	"ginjwt/models"
	"time"

	"github.com/golang-jwt/jwt"
	"github.com/google/uuid"
)

// 内部方法
func generateToken(userId string, tokenType string, expiredAt int64, issuedAt int64,
	issuer string, jti string) (string, error) {

	conf := config.GetConfig()

	claims := &models.AuthClaims{
		UserId:    userId,
		TokenType: tokenType,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expiredAt,
			IssuedAt:  issuedAt,
			Issuer:    issuer,
			Id:        jti,
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	t, err := token.SignedString([]byte(conf.GetString("AUTH.SECRET_KEY")))

	return t, err
}

// 生成access token
func GetAccessToken(username string) string {
	conf := config.GetConfig()
	tokenType := conf.GetString("TOKEN.ACCESS_TOKEN_TYPE")

	// 注意转换
	// expiredAt := time.Now().Add(time.Minute * 5).Unix()
	num := conf.GetInt64("TOKEN.ACCESS_TOKEN_LIFETIME")
	expiredAt := time.Now().Add(time.Minute * time.Duration(num)).Unix()

	IssuedAt := time.Now().Unix()
	issuer := conf.GetString("ISSUER")
	jti := uuid.New().String()

	token, err := generateToken(username, tokenType, expiredAt, IssuedAt, issuer, jti)

	if err != nil {
		panic(err)
	}
	return token
}

// 生成refresh token
func GetRefreshToken(username string) string {
	conf := config.GetConfig()
	tokenType := conf.GetString("TOKEN.REFRESH_TOKEN_TYPE")

	// expiredAt := time.Now().Add(time.Hour * 24).Unix()
	num := conf.GetInt64("TOKEN.REFRESH_TOKEN_LIFETIME")
	expiredAt := time.Now().Add(time.Hour * time.Duration(num)).Unix()
	// expiredAt := time.Now().Add(time.Second * time.Duration(num)).Unix()

	IssuedAt := time.Now().Unix()
	issuer := conf.GetString("TOKEN.ISSUER")
	jti := uuid.New().String()

	token, err := generateToken(username, tokenType, expiredAt, IssuedAt, issuer, jti)
	if err != nil {
		panic(err)
	}

	return token
}

// 解析用户传过来的token是否有效
func ValidateToken(tokenString string) (*jwt.Token, error) {
	conf := config.GetConfig()

	return jwt.ParseWithClaims(tokenString, &models.AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
		if _, isValid := token.Method.(*jwt.SigningMethodHMAC); !isValid {
			return nil, fmt.Errorf("无效口令: %v", token.Header["alg"])
		}
		return []byte(conf.GetString("AUTH.SECRET_KEY")), nil
	})
}
